import { ClientSocket } from "./ClientSocket";
import { ClientDealer } from "./ClientDealer";
import { Encrypter } from "../../Encrypters/Encrypter";
import { EncrypterManager } from "../../Managers/EncrypterManager";
import { IClientMessage } from "../../Interfaces/Sockets/IClientMessage";
import { ClientMessage } from "./ClientMessage";
import { IReceiveHandler } from "../../Interfaces/Sockets/IReceiveHandler";
import { HandlerManager } from "../../Managers/HandlerManager";
import { CryptoUtility } from "../../../Crypto/CryptoUtility";
import { IDispose } from "../../Interfaces/IDispose";

export class Client implements IDispose
{
    
    public static ClassName:string = "Client";
    public repeatConnectCount:number = 1;
    private onConnected:Function;
    private onClosed:Function;
    private onClientData:Function;
    private onError:Function;
    private onTimeOut:Function;
    private thisObject:any;
    private _clientName:string = null;
    private currentRepeat:number = 0;
    private socket:ClientSocket;
    private dealer:ClientDealer;
    private encrypter:Encrypter;
    private address:string;
    public constructor()
    {
        this._clientName = "Client";
        this.socket = new ClientSocket();
        this.dealer = new ClientDealer();
        this.socket.timeOut = 2000;
        this.socket.addCallBacks(this,this.onSocketConnected,this.onGetSocketData,this.onSocketClosed,this.onSocketError,this.onSocketTimeOut);
    }
    public addCallBacks(thisObject:any,onConnect:Function,onClientData:Function, onClose:Function, onError:Function,onTimeOut:Function):void 
    {
        this.onConnected = onConnect;
        this.onClosed = onClose;
        this.onClientData = onClientData;
        this.onError = onError;
        this.onTimeOut = onTimeOut;
        this.thisObject = thisObject;
    }


    // /api/Connect
    public connect(IP:string,port:number,param:string,userName?:string): void
    {
        this.currentRepeat = 0;
        let user = "";
        if(userName != "" && userName != null){
            user = "?userName=" +  userName
        }
        this.connectURL(IP+":"+port + param + user);
    }
    public connectURL(url:string):void
    {
        if(url.indexOf("ws://")==-1)url = "ws://"+url;
        this.address = url;
        this.socket&&this.socket.connectByUrl(url);
    }
    private onSocketConnected():void
    {
        if(this.onConnected!=null)
        {
            if(this.onConnected.length==0)this.onConnected.call(this.thisObject);
            else if(this.onConnected.length==1)this.onConnected.call(this.thisObject,this);
        }
    }

    private onGetSocketData():void
    {

        let msgBytes = this.socket.socketBytes;
        if(msgBytes.length==0)return;
        while(msgBytes.length>0)
        {
            var msg:ClientMessage = ClientMessage.Get();
            var jsonData = msgBytes.shift();
            msg.parser(jsonData);

            var handler:IReceiveHandler = this.dealer.getHandler(msg.id);
            if(handler!=null)handler.onDeal(this,msg);
            else
            {
                console.log("[Client "+this.clientName+"]未设置用于处理 id="+msg.id+" 的 ClientHandler",JSON.stringify(msg.content));
            }
            if(this.onClientData!=null)
            {
                if(this.onClientData.length==0)this.onClientData.call(this.thisObject);
                else if(this.onClientData.length==1)this.onClientData.call(this.thisObject,this);
                else if(this.onClientData.length==2)this.onClientData.call(this.thisObject,this,msg);
            }
            msg.dispose();
        }
        
        
        //console.log(CryptoUtility.GetString(CryptoUtility.ConvertWordArray(msgBytes)));
        
        return;
        // var packetID:number = msgBytes.shift();
        // var msg:ClientMessage = ClientMessage.Get(packetID);
        // msg.parser(CryptoUtility.GetString(CryptoUtility.ConvertWordArray(msgBytes)));
        // this.socket.socketBytes.length = 0;
        // this.onGetReceiveMessage(msg);
        // var packetID:number = this.encrypter.GetPacketID(msgBytes);
        // var bytes:any = this.encrypter.DecodeSocketData(msgBytes);
        // var msg:ClientMessage = ClientMessage.Get(packetID);
        // msg.parser(this.encrypter.GetString(bytes));

        // var handler:IReceiveHandler = this.dealer.getHandler(packetID);
        // if(handler!=null)handler.onDeal(this,msg);
        // else
        // {
        //     console.log("[Client "+this.clientName+"]未设置用于处理 PacketID=0x"+packetID.toString(16)+" 的 ClientHandler",JSON.stringify(msg.content));
        // } 

    }

    protected onGetReceiveMessage(msg:ClientMessage):void
    {

    }
    protected onSocketClosed():void
    {
        //console.log("[Client "+this.clientName+"]===>",this.address,"关闭");
        if(this.onClosed!=null)
        {
            if(this.onClosed.length==0)this.onClosed.call(this.thisObject);
            else if(this.onClosed.length==1)this.onClosed.call(this.thisObject,this);
        }
    }
    protected onSocketError():void
    {
        this.currentRepeat++;
        if(this.currentRepeat<this.repeatConnectCount)
        {
            this.socket.reconnect();
            return;
        }
        console.log("[Client "+this.clientName+"]===>连接",this.address,"失败！！！");
        if(this.onError!=null)
        {
            if(this.onError.length==0)this.onError.call(this.thisObject);
            else if(this.onError.length==1)this.onError.call(this.thisObject,this);
        }
    }
    protected onSocketTimeOut():void
    {
        this.currentRepeat++;
        if(this.currentRepeat<this.repeatConnectCount)
        {
            this.socket.reconnect();
            return;
        }
        console.log("[Client "+this.clientName+"]===>连接",this.address,"超时！！！");
        if(this.onTimeOut!=null)
        {
            if(this.onTimeOut.length==0)this.onTimeOut.call(this.thisObject);
            else if(this.onTimeOut.length==1)this.onTimeOut.call(this.thisObject,this);
        }
    }
    public sendMessage(msg: any):void
    {
        this.socket.sendString(msg.content);
        msg.dispose();
        //
        // 屏蔽所有数据加密
        // bytes = this.encrypter.EncodeSocketData(msg.packetID,bytes);
        //this.socket.send(msg);
        //msg.dispose();
    }
    public get isConnected():boolean{return this.socket&&this.socket.connected;}
    public get clientName():string{return this._clientName;}
    public set clientName(value:string)
    {
        this._clientName = value;
        this.encrypter = EncrypterManager.GetEncrypter(value);
        // HandlerManager.SetClientHandler(this);
    }
    public clearHandlers():void{this.dealer&&this.dealer.clear();}
    public addHandler(key:any, handler:IReceiveHandler,isForce:boolean = false):void{this.dealer&&this.dealer.addHandler(key,handler,isForce);}
    public removeHandler(key:any):void{this.dealer&&this.dealer.removeHandler(key);}
    public close():void{
        this.socket&&this.socket.close();
    }

    public dispose(): void 
    {
        this.onError = null;
        this.onClosed = null;
        this.onTimeOut = null;
        this.onConnected = null;
        this.onClientData = null;
        this.close();
        this.clearHandlers();
        this.socket&&this.socket.dispose();
        this.dealer&&this.dealer.dispose();
        this.encrypter = null;
        this.thisObject = null;
        this.socket = null;
        this.dealer = null;
    }
}